Hooks
This page gives specific examples and reference for implementing hooks in MWS. For more information and a description of hooks, see the hooks section in the user guide.Available Hooks
The following table lists the available hooks for each resource with their associated HTTP method and description.| Name | HTTP Method | Description |
|---|---|---|
| beforeList | GET | Runs before an API call that lists resources. ex: GET /rest/jobs |
| afterList | GET | Runs after an API call that lists resources. |
| beforeShow | GET | Runs before an API call that returns a single resource. ex: GET /rest/jobs/job.1 |
| afterShow | GET | Runs after an API call that returns a single resource. |
| beforeSave | POST | Runs before an API call that saves a new resource. ex: POST /rest/jobs |
| afterSave | POST | Runs after an API call that returns a single resource. |
| beforeUpdate | PUT | Runs before an API call that returns a single resource. ex: PUT /rest/jobs/job.1 |
| afterUpdate | PUT | Runs after an API call that returns a single resource. |
| beforeDelete | DELETE | Runs before an API call that returns a single resource. ex: DELETE /rest/jobs/job.1 |
| afterDelete | DELETE | Runs after an API call that returns a single resource. |
If a resource does not support a certain operation, any hooks for that operation will simply be ignored, such asbeforeSaveandafterSavehooks for the Node resource, where saving is not supported.
Available Properties
The following table lists the properties, objects, and methods available in all hooks. Note that although it is possible to directly call therender*
methods in the after hooks, it is not recommended. Please see the user guide for more information.| Name | Type | Description |
|---|---|---|
| params | Map | Contains all URL parameters as well as the body of the request as parsed JSON. |
| request | HttpServletRequest | Contains properties of the HTTP request. |
| response | HttpServletResponse | Contains properties of the HTTP response which can be modified directly. |
| session | HttpSession | Contains the session parameters which can be modified directly. |
| flash | Map | Temporary storage that stores objects within the session for the next request only. |
| controllerName | String | The name of the controller responding to the request. Only available in before hooks. |
| actionName | String | The name of the action to be run on the controller. Only available in before hooks. |
The parsed JSON may be accessed inIn addition, several methods are available to the hooks. These are described in the following sections.beforehooks as a simple groovy Map withparams[controllerName].
Redirect
Theredirect method may be used to redirect the request to another API call or an arbitrary URL.redirect(uri:'/rest/jobs') // uri is used for internal redirection within MWS redirect(url:'http://adaptivecomputing.com') // url is used for external redirection redirect(uri:'http://adaptivecomputing.com', params:[lang:'en']) // params may be used for URL parameters
The redirect method will use the GET HTTP method for the resulting redirected request.See the redirect method's documentation for more information.Rendering Objects, Lists, or Messages
There are severalrender* methods available to handle any case where objects or lists are desired to be rendered directly from the hook
without continuing to the API call. Three different methods may be used depending on the desired output object type:Render Object
// Object that should be rendered as JSON
def objectToRender = …
// HTTP response code (bad request)
def responseCode = 400// Render a simple object
renderObject(objectToRender)
// Render a simple object with a custom response code
renderObject(objectToRender, responseCode)Render List
// List that should be rendered as JSON def listToRender = … // If the totalCount property differs from resultCount, use this value instead def totalCount = … // HTTP response code (bad request) def responseCode = 400// Render a simple list // Dynamically adds "resultCount" and "totalCount" properties based on the size of the input list renderList(listToRender) // Render a simple list with a custom "totalCount" renderList(listToRender, totalCount) // Render a simple list without changing the "totalCount" but with a custom response code renderList(listToRender, null, responseCode) // Render a simple list with a custom "totalCount" and response code renderList(listToRender, totalCount, responseCode)
Render Message(s)
// Messages def messageToRender = "Single message" def messagesListToRender = ["Message 1", "Message 2"] // HTTP response code (bad request) def responseCode = 400// Render messages as an object with a property of "messages" containing a list of the messages passed in renderMessages(messageToRender) renderMessages(messageToRender, responseCode) // Supports either a single String or list of Strings renderMessages(messagesListToRender) renderMessages(messagesListToRender, responseCode)
It is not recommended to call any of these methods from an after hook.Render
Less commonly used, therender method is also available directly. This may be used to render text directly, change the content-type
of the output, and many other functions. See the render method's documentation
for more information.It is not recommended to call this method from an after hook.Serialize Objects
TheserializeObject and serializeList methods may be used to convert a custom object or list respectively into a format usable
for returning in the after hooks. Simply pass in the object or list and a serialized version will be returned from the method.def afterShow = {
def objectToRender = …
def serializedObject = serializeObject(objectToRender)
return serializedObject
}def afterShow = {
def listToRender = [...]
def serializedList = serializeList(listToRender)
return serializedList
}Error Handling
Error handling is only available inafter hooks by using the following check:if (!isSuccess()) { // Handle error return … // False or modified object/list to render }
Usage Examples
Override an API Call
The following hook would serve to override an entire API call, the list call in this case, and return amessages list containing
a single element of "Action is not supported" and a HTTP response code of 405 (Method Not Allowed):def beforeList = {
renderMessages("Action is not supported", 405)
return false
}vms.groovy file:def beforeDelete = {
renderMessages("Virtual Machine deletion is not allowed", 405)
return false
}Add An Additional Property During Job Creation
To add an additional property to a job definition during creation, create abeforeSave hook in the jobs.groovy file as follows:def beforeSave = {
// params[controllerName] is equivalent to params["job"] or params.job
params[controllerName].user = "myuser"
}myuser.Redirect Based on URL Parameter
To redirect an API call if a certain URL parameter exists, create abeforeSave hook in the jobs.groovy file as follows:def beforeSave = {
if (params.external) {
redirect(url:'http://example.com/create-job')
return false; // Stop API call
}
}PUT /rest/jobs?external=1 to redirect to GET http://example.com/create-job.Remove a Property From Getting a Single Job
To remove a property from the output of getting a single job, create anafterShow hook in the jobs.groovy file as follows:def afterShow = { o ->
o.discard("group")
return o
}group property of the job resource. Note again that these calls must use the
JSONArray and
JSONObject classes as mentioned in the user guide.Filter List Items
To filter the items in a list nodes request based on user provided query parameter in the URL, use the following in thenodes.groovy file.
A sample request that would activate the filter is http://localhost/mws/rest/nodes?filter-power=On.def afterList = { o ->
// Do not filter if the user did not ask for it
if (!params['filter-power'])
return o // o = {resultCount: x, totalCount: x, results:[...]} // Using a built-in groovy method findAll to return all
// list items that return true from the block
def results = o.results.findAll { node ->
// Includes the node only if the power equals the user input
return params['filter-power'].equalsIgnoreCase(node.power)
} // Sets the results on the return object and updates the counts
o.element("results", results)
o.element("resultCount", results.size())
return o
}nodes.groovy file.def afterList = { o ->
// o = {resultCount: x, totalCount: x, results:[...]} // Using a built-in groovy method findAll to return all
// list items that return true from the block
def results = o.results.findAll { node ->
// Includes the node only if the variable "included" is set to "true"
return node.variables?.included=="true"
} // Sets the results on the return object and updates the counts
o.element("results", results)
o.element("resultCount", results.size())
return o
}